import { Injectable, PipeTransform, ArgumentMetadata, HttpStatus, ValidationPipeOptions, } from "@nestjs/common";
import { ApiException } from "../exception/api.exception";
import { plainToClass } from "class-transformer";
import { validate } from "class-validator";
import { ApiErrorCode } from "../../ShareModule/enums/api-error-code";

@Injectable()
export class ApiParamsValidationPipe implements PipeTransform{
    private readonly options:ValidationPipeOptions;
    constructor(options?:ValidationPipeOptions){ this.options = options }

    async transform(value:any,metadata:ArgumentMetadata){
        const { metatype } = metadata;
        //如果参数是普通的js对象则不验证
        if(!metatype || !this.toValidate(metatype)) return value;

        //通过元数据和对象实例，构建原有类型
        const object = plainToClass(metatype,value);
        const errors = await validate(object, this.options);

        if(errors.length){
            //获取第一个没有通过验证的错误对象
            let error = errors.shift();
            let constraints = error.constraints;
            let contexts = error.contexts;

            //将未通过验证的字段的错误信息和状态码，以ApiException的形式抛给我们的2全局异常过滤器
            for(let key in constraints){
                const errorCode:number = contexts? contexts[key].errorCode : ApiErrorCode.ERROR;
                throw new ApiException(
                    constraints[key],
                    errorCode,
                    HttpStatus.BAD_REQUEST,
                )
            }
        }

        return object;
    }

    private toValidate(metatype:any):boolean{
        const types = [String,Boolean,Number,Array,Object];

        return !types.find(type => metatype ===type);
    }

}